/**
 * Copyright (c) 2022 Wei-Lun Hsu. All Rights Reserved.
 */
/** @file zb32l03x_hal_spi.h
 *
 * @author Wei-Lun Hsu
 * @version 1.0
 * @date 2022/07/12
 * @license
 * @description
 */

#ifndef __ZB32L03x_HAL_SPI_H
#define __ZB32L03x_HAL_SPI_H

#ifdef __cplusplus
extern "C" {
#endif

#include "zb32l03x_hal_def.h"

/** @addtogroup ZB32L03x_HAL_Driver
  * @{
  */

/** @addtogroup SPI
  * @{
  */
//=============================================================================
//                  Constant Definition
//=============================================================================
/** @defgroup SPI_Exported_Constants SPI Exported Constants
 * @{
 */

#define HAL_SPI_BLOCKING            (~0ul)

/**
 *  HAL_SPI_Mode SPI operating mode
 */
typedef enum HAL_SPI_Mode
{
    HAL_SPI_MODE_SLAVE  = 0x00000000U,   /*!< SPI communication is in Slave Mode.
                                            User MUST select a CS pin (SYSCON_PORTCR->SPIxSSN_SEL != 0) */
    HAL_SPI_MODE_MASTER = SPI_CR_MSTR,   /*!< SPI communication is in Master Mode       */

} HAL_SPI_ModeTypeDef;


/**
 *  HAL_SPI_Polarity SPI Clock Polarity
 */
typedef enum HAL_SPI_Polarity
{
    HAL_SPI_POLARITY_LOW    = 0x00000000U,  /*!< CPOL = 0 */
    HAL_SPI_POLARITY_HIGH   = SPI_CR_CPOL,  /*!< CPOL = 1 */

} HAL_SPI_PolarityTypeDef;


/**
 *  HAL_SPI_Phase SPI Clock Phase
 */
typedef enum HAL_SPI_Phase
{
    HAL_SPI_PHASE_1EDGE = 0x00000000U,      /*!< CPHA = 0 */
    HAL_SPI_PHASE_2EDGE = SPI_CR_CPHA,      /*!< CPHA = 1 */

} HAL_SPI_PhaseTypeDef;


/**
 *  HAL_SPI_NSS_Mode SPI NSS set
 */
typedef enum HAL_SPI_NSS_Mode
{
    HAL_SPI_NSS_LOW    = 0x00000000U,
    HAL_SPI_NSS_HIGH   = SPI_SSN_SSN,

} HAL_SPI_NSS_ModeTypeDef;



/**
 *  HAL_SPI_Prescaler SPI BaudRate Prescaler
 */
typedef enum HAL_SPI_Prescaler
{
    HAL_SPI_PCLK_PRESCALER_2     = 0x00000000U,                 /*!< SPI slave mode does NOT support this case  */
    HAL_SPI_PCLK_PRESCALER_4     = SPI_CR_SPR0,                 /*!< SPI slave mode does NOT support this case  */
    HAL_SPI_PCLK_PRESCALER_8     = SPI_CR_SPR1,
    HAL_SPI_PCLK_PRESCALER_16    = (SPI_CR_SPR0 | SPI_CR_SPR1),
    HAL_SPI_PCLK_PRESCALER_32    = SPI_CR_SPR2,
    HAL_SPI_PCLK_PRESCALER_64    = (SPI_CR_SPR2 | SPI_CR_SPR0),
    HAL_SPI_PCLK_PRESCALER_128   = (SPI_CR_SPR2 | SPI_CR_SPR1),

} HAL_SPI_PrescalerTypeDef;


/**
 * @brief  HAL SPI State structure definition
 */
typedef enum
{
    HAL_SPI_STATE_RESET      = 0x00U,    /*!< Peripheral not Initialized                         */
    HAL_SPI_STATE_READY      = 0x01U,    /*!< Peripheral Initialized and ready for use           */
    HAL_SPI_STATE_BUSY       = 0x02U,    /*!< an internal process is ongoing                     */
    HAL_SPI_STATE_BUSY_TX    = 0x03U,    /*!< Data Transmission process is ongoing               */
    HAL_SPI_STATE_BUSY_RX    = 0x04U,    /*!< Data Reception process is ongoing                  */
    HAL_SPI_STATE_BUSY_TX_RX = 0x05U,    /*!< Data Transmission and Reception process is ongoing */
    HAL_SPI_STATE_ERROR      = 0x06U     /*!< SPI error state                                    */
} HAL_SPI_StateTypeDef;

/** @defgroup HAL_SPI_Err SPI Error Code
 * @{
 */
typedef enum HAL_SPI_Err
{
    HAL_SPI_ERROR_NONE    = 0x00000000U,   /*!< No error             */
    HAL_SPI_ERROR_MODF    = 0x00000001U,   /*!< MODF error           */
    HAL_SPI_ERROR_OVR     = 0x00000002U,   /*!< OVR error            */
    HAL_SPI_ERROR_FRE     = 0x00000004U,   /*!< FRE error            */
    HAL_SPI_ERROR_FLAG    = 0x00000008U,   /*!< Flag:                */
    HAL_SPI_ERROR_TIMEOUT = 0x00000008U,   /*!< Xfer Timeout         */
} HAL_SPI_ErrTypeDef;

/**
 *  SPI_Flags_definition SPI Flags Definition
 */
typedef enum HAL_SPI_Flag
{
    HAL_SPI_FLAG_SPIF   = SPI_SR_SPIF,    /* SPI status flag: Tx ok flag */
    HAL_SPI_FLAG_WCOL   = SPI_SR_WCOL,    /* SPI status flag: write conflict  flag */
    HAL_SPI_FLAG_SSERR  = SPI_SR_SSERR,   /* SPI Error flag: Slave SSN flag */
    HAL_SPI_FLAG_MDF    = SPI_SR_MDF,     /* SPI Error flag: Master Mode error flag */

} HAL_SPI_FlagTypeDef;


/**
 * @}
 */  /* End of group SPI_Exported_Constants */


//=============================================================================
//                  Structure Definition
//=============================================================================
/** @defgroup SPI_Exported_Types SPI Exported Types
 * @{
 */


/**
 * @brief  SPI Configuration Structure definition
 */
typedef struct
{
    uint16_t                    DelayTicks;         /*!< Specifies the delay ticks of master/slave mode between data bytes.
                                                        ps. If DelayTimes = 0, use default value. */

    HAL_SPI_ModeTypeDef         Mode;               /*!< Specifies the SPI operating mode.
                                                        This parameter can be a value of @ref HAL_SPI_ModeTypeDef */

    HAL_SPI_PolarityTypeDef     CLKPolarity;        /*!< Specifies the serial clock steady state.
                                                        This parameter can be a value of @ref HAL_SPI_PolarityTypeDef */

    HAL_SPI_PhaseTypeDef        CLKPhase;           /*!< Specifies the clock active edge for the bit capture.
                                                        This parameter can be a value of @ref HAL_SPI_PhaseTypeDef */

    HAL_SPI_NSS_ModeTypeDef     NSS;                /*!< Specifies the NSS signal is Hight or low after Inint @ref HAL_SPI_NSS_ModeTypeDef */

    HAL_SPI_PrescalerTypeDef    BaudRatePrescaler;  /*!< Specifies the Baud Rate prescaler value which will be
                                                        used to configure the transmit and receive SCK clock.
                                                        This parameter can be a value of @ref HAL_SPI_PrescalerTypeDef
                                                        @note The communication clock is derived from the master
                                                        clock. The slave clock does not need to be set. */
} SPI_InitTypeDef;


typedef struct
{
    SPI_TypeDef                 *Instance;    /*!< Register base address                     */
    SPI_InitTypeDef             Init;         /*!< SPI communication parameters              */

    uint8_t                    *pTxBuffPtr;    /*!< Pointer to SPI Tx transfer Buffer        */

    uint16_t                   TxXferSize;     /*!< SPI Tx Transfer size                     */
    __IO uint16_t              TxXferCount;    /*!< SPI Tx Transfer Counter                  */

    uint8_t                    *pRxBuffPtr;    /*!< Pointer to SPI Rx transfer Buffer        */

    uint16_t                   RxXferSize;     /*!< SPI Rx Transfer size                     */
    __IO uint16_t              RxXferCount;    /*!< SPI Rx Transfer Counter                  */


    __IO HAL_SPI_StateTypeDef   State;        /*!< SPI communication state                   */

    HAL_LockTypeDef             Lock;         /*!< SPI locking object                        */
    __IO HAL_SPI_ErrTypeDef     ErrorCode;    /*!< SPI Error code                            */


} SPI_HandleTypeDef;




/**
 * @}
 */  /* End of group SPI_Exported_Types */

//=============================================================================
//                  Macro Definition
//=============================================================================
/** @defgroup SPI_Exported_Macros SPI Exported Macros
 * @{
 */



/**
 *  \brief  Check whether the specified SPI flag is set or not.
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \param [in] __FLAG__            The specifies flag to check.
 *                                  This parameter can be one of the following values, @ref HAL_SPI_FlagTypeDef:
 *                                  @arg SPI_FLAG_SPIF  : SPI status flag: Tx ok flag
 *                                  @arg SPI_FLAG_WCOL  : SPI status flag: write conflict  flag
 *                                  @arg SPI_FLAG_SSERR : SPI Error flag: Slave SSN flag
 *                                  @arg SPI_FLAG_MDF   : SPI Error flag: Master Mode error flag
 *  \return
 *      The new state of __FLAG__ (TRUE or FALSE).
 */
#define __HAL_SPI_GET_FLAG(__HANDLE__, __FLAG__)        ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__))


/**
 *  \brief  Enable the SPI peripheral.
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \return                         None
 */
#define __HAL_SPI_ENABLE(__HANDLE__)                        SET_BIT((__HANDLE__)->Instance->CR, SPI_CR_SPEN)


/**
 *  \brief  Disable the SPI peripheral.
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \return                         None
 */
#define __HAL_SPI_DISABLE(__HANDLE__)                       CLEAR_BIT((__HANDLE__)->Instance->CR, SPI_CR_SPEN)

/**
 *  \brief  Master set NSS (CS) signal to HIGH
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \return                         None
 */
#define __HAL_SPI_SET_NSS_HIGH(__HANDLE__)                  SET_BIT((__HANDLE__)->Instance->SSN, SPI_SSN_SSN)

/**
 *  \brief  Master set NSS (CS) signal to LOW
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \return                         None
 */
#define __HAL_SPI_SET_NSS_LOW(__HANDLE__)                   CLEAR_BIT((__HANDLE__)->Instance->SSN, SPI_SSN_SSN)

/**
 *  \brief  Get delay ticks of SPI
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \return
 *      delay ticks
 */
#define __HAL_SPI_GET_DELAY_TICKS(__HANDLE__)               ((__HANDLE__)->Init.DelayTicks)

/**
 *  \brief  Set delay ticks of SPI
 *
 *  \param [in] __HANDLE__          The specifies SPI Handle.
 *  \param [in] __DELAY__           Specifies the delay ticks of SPI
 *  \return                         None
 */
#define __HAL_SPI_SET_DELAY_TICKS(__HANDLE__, __DELAY__)    ((__HANDLE__)->Init.DelayTicks = (__DELAY__))

/**
 * @}
 */  /* End of group SPI_Exported_Macros */


//=============================================================================
//                  Public Function Definition
//=============================================================================
/** @addtogroup SPI_Exported_Functions
 * @{
 */

HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *pHSpi);
HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *pHSpi);


HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size, uint32_t Timeout_ms);
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t *pSize, uint32_t Timeout_ms);
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *pHSpi,
                                          uint8_t *pTxData, uint8_t *pRxData,
                                          uint16_t Size, uint32_t Timeout_ms);


HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *pHSpi,
                                             uint8_t *pTxData, uint8_t *pRxData,
                                             uint16_t Size);

uint16_t HAL_SPI_Calc_Delay(SPI_HandleTypeDef *pHSpi, uint32_t spi_sck);
uint32_t HAL_SPI_Get_SCK(SPI_HandleTypeDef *pHSpi);

/* MSP functions  *************************************************************/
void HAL_SPI_MspInit(SPI_HandleTypeDef *pHSpi);
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *pHSpi);


void HAL_SPI_IRQHandler(SPI_HandleTypeDef *pHSpi);
void HAL_SPI_TxCmpltCallback(SPI_HandleTypeDef *pHSpi);
void HAL_SPI_RxCmpltCallback(SPI_HandleTypeDef *pHSpi);
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *pHSpi);

/**
 * @}
 */  /* End of group SPI_Exported_Functions */

/**
 * @}
 */  /* End of group SPI */

/**
 * @}
 */  /* End of group ZB32L03x_HAL_Driver */


#ifdef __cplusplus
}
#endif

#endif
